#include "../inc/defs.h"

coordenada
asignarPos(coordenada * vec, int dim)
{
	int aux;

	aux = randint(0,dim);
	return vec[aux];//devuelvo la estructura de la coordenada de ese pto//
	
}

coordenada *
buscaNespa( tablero tab, int *fin )
{
	int i, j, s;
	s = 0;
	*fin = 0;

	coordenada *vec;
	vec = NULL;

	for ( i = 0 ; (i < tab.opciones.dim.x) && ((*fin) == 0) ; i++ )
	{
		  vec = realloc ( vec, ((tab.opciones.dim.y) * (sizeof(coordenada))) * (i+1));

		 if ( vec != NULL )
		 {
			 for ( j = 0 ; (j < tab.opciones.dim.y) && (!(*fin)) ; j++ )
			 {
				 if ( tab.mat[i][j] == 0 )
				 {
					 vec[s].x = i;
					 vec[s].y = j;
					 s++;
				 }
			 }
		 }
		 else
		 {
			 (*fin) = 1;
		 }
	}
	vec[s].x = -1;
	vec[s].y = -1;
	if ( s <= tab.opciones.cantagrega)
	{
		(*fin) = 0;
		vec = NULL;
	}
	else
	{
	  (*fin) = s-1; //en fin va a quedar la dimension del vector (sin contar{-1,-1})
	}
	return vec;
}

//------------------------------------------------------------------------
//libera el espacio de memoria dinamica reservada durante el juego
void
liberarMat(char **matriz, coordenada dim)
{
        int i;
		for(i=0;i<dim.x;i++)
        {
                free(matriz[i]);
		}
		free(matriz);
        return;

}


//-------------------------------------------------------------------------
void
asignarColor ( char **matriz, coordenada coord, int colores )
{
	int colormin = 1;

	matriz[coord.x][coord.y] = randint(colormin, colores);
	return;
}

//--------------------------------------------------------------------------
int
randint(int cotinf, int cotsup)
{
	return cotinf + (rand()/(double)RAND_MAX)*(cotsup - cotinf + 1);
}

//--------------------------------------------------------------------------
int
calcular_puntaje(int bolitas,int minfila )
{
	int puntaje;
	
	/*entra si la cantidad de bolitas alineadas es mayor o igual al minimo por linea establecido al 
	comienzo del juego*/
	if(bolitas>(minfila-1)) 
	{
	/*el puntaje se establece en relacion a la cantidad minima de bolitas por linea establecida
	este valor se obtiene de restarle la cantidad minima de filas (minfil) a la cantidad de bolitas alineadas (bolitas )*/
		switch(bolitas-minfila)
		{
	
			case 0: puntaje= 1;
			break;
			case 1: puntaje=2;
			break;
			case 2: puntaje=4;
			break;
			case 3: puntaje=6;
			break;
			default : puntaje=8;
	}
	
	}
	return puntaje;
}
//--------------------------------------------------------------------------------
int
esvacio(char *vec, int dim)
{
	int i;
	
	for(i = 0; i < dim; i++)
	{
		if(vec[i] != ' ')
			return 1;
	}
	return 0;
}
//---------------------------------------------------------------------------------
char**
armartablero(int fil, int col)
{
	int i;
	char**mat;
	if((mat=calloc(fil,sizeof(char*)))==NULL)
		return NULL;
	for(i=0;i<fil;i++)
	{
		if(((mat[i]=calloc(col,sizeof(char)))==NULL))
			return NULL;
	}
return mat;
}
//------------------------------------------------------------------------------------
//le paso el vector de ptos, y un pto, y me fijo si ese punto pertenece al vector. Si esta en el vector devuelve 0,
//sino devuelve 1.
int
comparaptos(coordenada pto, coordenada * pto1, int dim)
{
    int flag = 1;

	for(;dim != 0; dim--)
	{
		if(pto.x == pto1[dim].x && pto.y == pto1[dim].y)
			flag = 0;
	}
	return flag;

}
//-------------------------------------------------------------------------------------
// 		ACA VA TODA LA FUNCION ALINEA!!!
//guarda en el vector de coordenadas la boca y la cola de la linea a borrar
void
guardaPos ( coordenada **vec, int i, int j, int k, int r, int *s )
{
	*vec = realloc( *vec, (((sizeof(coordenada))*2)+ (*s)) );

	if ( vec != NULL )
	{
		(*vec)[(*s)].x = i ;
		(*vec)[(*s)++].y = j ;
		(*vec)[(*s)].x = k ;
		(*vec)[(*s)++].y = r ;
	}
}


void
horizontal ( int i, int j, int dim, char **mat, int cant, int *s, coordenada **vec, int H, int V )
{
	int k;
	int color = mat[i][j];
		
	if ( ((i-1)*V) < 0 || ((j-1)*H) < 0 || (mat[i-V][j-H] != color) )
	{
		for ( k = (H*(j+1) + V*(i+1)) ; (k<dim) && (mat[(V*k)+(H*i)][(V*j)+(H*k)] == color) ; k++ )
		{
			;
		}
		if ( k- ((H*j)+(V*i)) >= cant )
		{
			guardaPos ( vec, i, j, ((H*i)+(V*(k-1))), ((H*(k-1))+(V*j)), s );
		}
	}
}

void
diagonal( tablero tab, int i, int j, int *s, coordenada **vec, int D, int I)
{
	int k, r;
	int color = tab.mat[i][j];
	
	if ( (i-1)<0 || ((j-1)*D)<0 || ((j+1)*I) == tab.opciones.dim.y ||tab.mat[i-1][j-1+(I*2)] != color )
	{
		for ( k = i+1 , r = (j+1-I-I) ; (k<tab.opciones.dim.x) && (tab.mat[k][r] == color) ; k++)
		{
		  if ( D )
		  {
		    r++;
		  }
		  if ( I )
		  {
		    r--;
		  }
		}
		if ( (k-i) >= tab.opciones.alinea )
		{
			guardaPos ( vec, i, j, (k-1), (D*(r-1)+ I*(r+1)), s );
		}
	}		
}

void
borrar ( tablero *tab, coordenada *vec, int *s, int * puntaje, int flag ) /*flag = 1 si viene de un movimiento o 0 si viene de agregar bolitas*/
{
	int i, k, j;

  	for ( k = 0 ; (k+1) < *s ; k++ )
  	{
	   	if ( vec[k].x == vec[k+1].x ) /* se mueve horizontalmente*/
    	{
      		if ( flag )
      		{
				(*puntaje) += calcular_puntaje ( ((vec[k+1].y)-(vec[k].y)+1), tab->opciones.alinea );
      		}
      		for ( j = vec[k].y ; j <= vec[k+1].y ; j++ )
      		{
				tab->mat[(vec[k].x)][j] = 0;
      		}
		}
    	else
    	{
      		if ( vec[k].y == vec[k+1].y ) /*se mueve verticalmente*/
      		{
				if ( flag)
				{
	  				(*puntaje) += calcular_puntaje ( ((vec[k+1].x)-( vec[k].x) +1 ), tab->opciones.alinea );
				}
				for ( i = vec[k].x ; i <= vec[k+1].x ; i++ )
				{
	  				tab->mat[i][(vec[k].y)] = 0;
				}
			}
			else
			{
	  			if ( vec[k].y < vec[k+1].y ) /*se mueve en diagonal a la derecha*/
	  			{
	    			if ( flag)
					{
		  				(*puntaje) += calcular_puntaje ( ((vec[k+1].y)-( vec[k].y)+1), tab->opciones.alinea );
					}
		   			for ( i = vec[k].x, j = vec[k].y ; (i <= vec[k+1].x) /*&& (j <= vec[k+1].y)*/ ; i++, j++ )
		   			{
	      				tab->mat[i][j] = 0;
	    			}
				}
	    		else /*se mueve en diagonal para la izq*/
		   		{
	     			if ( flag )
	      			{
						(*puntaje) += calcular_puntaje ( ((vec[k+1].x)-(vec[k].x)+1 ), tab->opciones.alinea );
	      			}
	      			for ( i = vec[k].x , j = vec[k].y ; (i<= vec[k+1].x) ; i++, j-- )
	      			{
						tab->mat[i][j] = 0;
	      			}
	    		}
	  		}
		}
	}
}

//devuelve 1 si puedo alinear, 0 sino
int
alinea ( tablero tab, int *puntaje, int flag ) 
{
	int i, j, s, k, r, cant;
	coordenada * vec;
	s = 0;
	vec = NULL;
	//s va a marcar la dimension del vector

	for ( i = 0 ; i < tab.opciones.dim.x ; i++)
	{
		for ( j = 0 ; j< tab.opciones.dim.y ; j++)
		{
			if ( tab.mat[i][j] != 0 )
			{
				horizontal ( i, j, tab.opciones.dim.y, tab.mat, tab.opciones.alinea, &s, &vec, 1, 0 );
	/*vertical-->*/		horizontal ( i , j, tab.opciones.dim.x, tab.mat, tab.opciones.alinea, &s, &vec, 0, 1 );
	/*derecha*/		diagonal ( tab, i, j, &s, &vec, 1, 0 );
	/*izq*/			diagonal ( tab, i, j, &s, &vec, 0, 1 );
			}
		}	
	}
	if ( s > 0 )
	{
	  	borrar ( &tab, vec, &s, puntaje, flag );
		return 1;
	}
	else
	
	{
		return 0;
	}
	  free(vec);
}

//-------------------------------------------------------------------------------------------
//si devuelve en 1 existe camino, 0 sino
void
auxExisteCam( tablero * juego, int i, int j, int k, int r, int *e )
{
        if ( ((i == k) && ((j+1)==r)) || ( ((i-1)==k) && (j==r)) || ( (i==k) && ((j-1)==r)) || ( ((i+1)==k) && (j==r)) )
        {
                *e = 1;
        }

        if ( ((j+1)< juego->opciones.dim.y) &&  (juego->mat[i][j+1] == 0))
        {
                auxExisteCam ( juego,i, (j+1), k, r , e);
        }
        if ( ((i-1)>= 0) && (juego->mat[i-1][j] == 0) )
        {
                auxExisteCam ( juego, (i-1), j, k , r , e);
        }
        if ( ((j-1)>= 0) && (juego->mat[i][j-1] == 0) )
        {
                juego->mat[i][j] = -1;
                auxExisteCam ( juego, i , (j-1), k, r , e);
        }
        if ( ((i+1)<juego->opciones.dim.x) && (juego->mat[i+1][j] == 0) )
        {
                juego->mat[i][j] = -1;
                auxExisteCam ( juego, (i+1), j, k, r, e );
        }
}

int
existeCam ( tablero*juego, int i, int j, int k, int r, int *e )
{
	char aux, aux2;
	aux = juego->mat[i][j];
	aux2 = juego->mat[k][r];
	
        auxExisteCam ( juego, i, j, k, r, e );
        int s, t;
        for ( s = 0 ; s < juego->opciones.dim.x ; s++ )
        {
                for ( t = 0 ; t < juego->opciones.dim.y ; t++ )
                {
                        if ( juego->mat[s][t] == -1 )
                        {
                                juego->mat[s][t] = 0;
                        }
                }
        }
		juego->mat[i][j] = aux;
		juego->mat[k][r] = aux2;
		
        return *e;
}
//----------------------------------------------------------------------------------------
void 
copiarMat(coordenada dim, char ** Mat, char ** matAux)
{
	int i,j;
	
	for(i = 0; i < dim.x; i++)
		for(j = 0; j < dim.y; j++)
			Mat[i][j] = matAux[i][j];
}
//---------------------------------------------------------------------------------
//devuelve 1 si se puede, 0 sino
int
saveFile ( actual *juego, char *nombre )
{
	int i, j;
	FILE * miArch;
	
	miArch = fopen(nombre,"w");
	
	if ( miArch !=NULL )
	{
		fwrite(&(juego->Tjuego), sizeof(int), 1, miArch);
		if ( juego->Tjuego == MODOTIEMPO )
		{
			fwrite(&(juego->Tjuego), sizeof(int), 1, miArch);
		}
		if ( juego->Tjuego == DOS_JUGADORES )
		{
			fwrite(&(juego->proxturno), sizeof(int), 1, miArch);
			fwrite(&(juego->puntaje2), sizeof(int), 1, miArch);
			fwrite(&(juego->Tjuego), sizeof(int), 1, miArch);
			fwrite(&(juego->dimfil), sizeof(int), 1, miArch);
			fwrite(&(juego->dimcol), sizeof(int), 1, miArch);
			for ( i = 0 ; i< juego->dimfil ; i++ )
			{
				for ( j = 0; j< juego->dimcol ; j++ )
				{
					fputc(juego->sec2[i][j], miArch);
				}
			}
		}
	
		fwrite(&(juego->cantcolor), sizeof(int), 1, miArch);
		fwrite(&(juego->cantalinea), sizeof(int), 1, miArch);		
		fwrite(&(juego->cantagrega), sizeof(int), 1, miArch);
		fwrite(&(juego->puntaje1), sizeof(int), 1, miArch);
		for ( i=0 ; i< juego->dimfil ; i++ )
		{
			for ( j=0 ; j< juego->dimcol ; j++ )
			{
				fputc((juego->sec1[i][j]), miArch);
			}
		}
		fclose(miArch);
	}
	else
	{	
		return 0;
	}
	return 1;
}

//devuelve 1 si se puede, 0 sino
int loadFile ( actual * juego, char * nombre )
{
	int i, j;
	FILE * cargArch;
	
	cargArch = fopen(nombre, "r" );
	if ( cargArch != NULL )
	{
		fread(&(juego->Tjuego), sizeof(int), 1, cargArch );
		if ( juego->Tjuego == MODOTIEMPO )
		{
			fread(&(juego->Tjuego), sizeof(int), 1, cargArch);
		}
		else
		{
			juego->Trestante = 0;
		}
		if ( juego->Tjuego == DOS_JUGADORES )
		{
			fread(&(juego->proxturno), sizeof(int), 1, cargArch);
			fread(&(juego->puntaje2), sizeof(int), 1, cargArch);
			fread(&(juego->Tjuego), sizeof(int), 1, cargArch);
			fread(&(juego->dimfil), sizeof(int), 1, cargArch);
			fread(&(juego->dimcol), sizeof(int), 1, cargArch);
			for ( i = 0 ; i< juego->dimfil ; i++ )
			{
				for ( j = 0; j< juego->dimcol ; j++ )
				{
					juego->sec2[i][j] = fgetc(cargArch);
				}
			}
		}

		if ( juego-> dimfil>=DIMMAX || juego-> dimcol>= DIMMAX )
		{
			error(0);
			fclose(cargArch);
			return 0;
		}		
		fread(&(juego->cantcolor), sizeof(int), 1, cargArch);
		fread(&(juego->cantalinea), sizeof(int), 1, cargArch);
		fread(&(juego->cantagrega), sizeof(int), 1, cargArch);
		fread(&(juego->puntaje1), sizeof(int), 1, cargArch);
		for ( i=0 ; i< juego->dimfil ; i++ )
		{
			for ( j=0 ; j< juego->dimcol ; j++ )
			{
				juego->sec1[i][j] = fgetc(cargArch);
			}
		}

		fclose(cargArch);
	}
	else
	{	
		return 0;
	}
	return 1;
}